package com.message.tcp.ip.socket.util;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Random;

import org.apache.log4j.Logger;
import org.jpos.iso.ISOException;
import org.jpos.iso.packager.GenericPackager;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.message.tcp.ip.socket.configure.service.CardAccountService;
import com.message.tcp.ip.socket.configure.service.DataElementService;

public class MessageDefinition {
	public static final Logger logger = Logger.getLogger(MessageDefinition.class);
	private static GenericPackager packager;
	private static CardAccountService cardAccountService;
	private static DataElementService dataElementService;
	static{
		try{
			ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
			cardAccountService = (CardAccountService) context.getBean("cardAccountService");
			dataElementService = (DataElementService) context.getBean("dataElementService");
			packager = new GenericPackager("configure/messageDefinition.xml");
			
		}
		catch(ISOException ex){
			logger.debug("Exception occur while try to initiate generic packager", ex);
		}
	}
	
	public static GenericPackager getGenericPackager(){
		return packager;
	}
	public static String integerFormater(int number,String format){
		DecimalFormat decimalFormat = new DecimalFormat(format);
		return decimalFormat.format(number);
	}
	/**
	 * Configurable Data Element
	 * @return card number
	 */
	public static String buildField02(){
		return cardAccountService.getCardNumber();
	}
	/**
	 * Static Data Element
	 * Processing code set for Balance Inquiry and Cash Withdrawal
	 */
	public static final String BINQ00 = "300000";
	public static final String BINQ01 = "301000";
	public static final String BINQ02 = "302000";
	public static final String BINQ03 = "303000";
	
	public static final String CWD00 = "010000";
	public static final String CWD01 = "011000";
	public static final String CWD02 = "012000";
	public static final String CWD03 = "013000";
	
	/**
	 * Configurable Data Element
	 * @return Primary Account Number
	 */
	public static String buildField04(){
		return dataElementService.getDataValue("DE4");
	}
	/**
	 *  Dynamic Date Element
	 *  
	 * @param field11
	 * @return retrieval reference number
	 */
	public static String buildField37(String field11) {
		GregorianCalendar gc = new GregorianCalendar();
		int jDate = gc.get(GregorianCalendar.DAY_OF_YEAR);
		DecimalFormat numFormatter = new DecimalFormat("000");
		String jDateFormat = numFormatter.format(jDate);
		SimpleDateFormat simpleDateFormatY = new SimpleDateFormat("yyyy");
		String y = simpleDateFormatY.format(new java.util.Date()).substring(3);
		SimpleDateFormat simpleDateFormatH = new SimpleDateFormat("HH");
		String hh = simpleDateFormatH.format(new java.util.Date());
		String field37 = y + jDateFormat + hh + field11;
		return field37;
	}
	/** Dynamic Data Element
	 * @return transaction date time
	 */
	public static String buildField07() {
		java.util.Date uDate = new java.util.Date();
		SimpleDateFormat sDateFormat = new SimpleDateFormat("MMddHHmmss");
		return sDateFormat.format(uDate);
	}
	private static final int START = 1;
	private static final int END = 999999;
	public static String buildField11(){
		Random random = new Random();
		long range = (long)START - (long)END + 1;
	    long fraction = (long)(range * random.nextDouble());
	    int randomNumber =  (int)(fraction + START); 
		return integerFormater(randomNumber,"000000");
	}
	
	/**
	 *  build Data Element 70 network message code
	 */
	
	public static final String SIGNON 	= "001";
	public static final String SIGNOFF 	= "002";
	public static final String KEYEXC 	= "161";
	public static final String STARTADV = "010";
	public static final String STOPADV 	= "020";
	public static final String ECHO 	= "301";
	/**
	 * 
	 * @return Local Time
	 */
	public static String buildField12(){
		Calendar cal = Calendar.getInstance();
		Date date = cal.getTime();
		SimpleDateFormat format = new SimpleDateFormat("HHmmss");
		return format.format(date);
	}
	/**
	 * Dynamic Data Element
	 * @return Local Date
	 */
	public static String buildField13() {
		Calendar cal = Calendar.getInstance();
		Date date = cal.getTime();
		SimpleDateFormat format = new SimpleDateFormat("MMdd");
		return format.format(date);
	}
	/**
	 * Configurable Data Element
	 * @return Expired Date
	 */
	public static String buildField14(){
		return dataElementService.getDataValue("DE14");
	}
	/**
	 * Dynamic Data Element
	 * @return Settlement Date
	 */
	public static String buildField15(){
		Calendar cal = Calendar.getInstance();
		Date date = cal.getTime();
		SimpleDateFormat format = new SimpleDateFormat("MMdd");
		return format.format(date);
	}
	/**
	 * Configurable Data Element
	 * @return Merchant Category Code
	 */
	public static String buildField18(){
		return dataElementService.getDataValue("DE18");
	}
	/**
	 * Configurable Data Element
	 * @return Country Code
	 */
	public static String buildField19(){
		return dataElementService.getDataValue("DE19");
	}
	/**
	 * Configurable Data Element
	 * @return Point of Service Entry Mode
	 */
	public static String buildField22(){
		return dataElementService.getDataValue("DE22");
	}
	/**
	 * Configurable Data Element
	 * @return Point of service Condition Code
	 */
	public static String buildField25(){
		return dataElementService.getDataValue("DE25");
	}
	/**
	 * 
	 * @return Transaction Fee
	 */
	public static String buildField28(){
		int fee = Integer.parseInt(dataElementService.getDataValue("DE28"));
		String de28 = "D"+integerFormater(fee,"00000000");
		return de28;
	}
	/**
	 * 
	 * @return Acquiring Institution Identification Code
	 */
	public static String buildField32(){
		return dataElementService.getDataValue("DE32");
	}
	/**
	 * 
	 * @return Track 2 data
	 */
	public static String buildField35(){
		String card = cardAccountService.getCardNumber();
		String cav = cardAccountService.getCav(card);
		String exp = cardAccountService.getExpiryDate(card);
		String ADDITIONALDATA = "10100000"+cav+"00000";
		return card+"="+exp+ADDITIONALDATA;
	}
	/**
	 * Configurable Data Element
	 * @return response code
	 */
	public static final String buildField39(){
		return dataElementService.getDataValue("DE39");
	}
	/**
	 * Configurable Data Element
	 * @return terminal Identification
	 */
	public static String buildField41(){
		return dataElementService.getDataValue("DE41");
	}
	/**
	 * Configurable Data Element
	 * @return acquirer identification
	 */
	public static String buildField42(){
		String de42 = String.format("%15s", dataElementService.getDataValue("DE42"));
		return de42;
	}
	/**
	 * Configurable Data Element
	 * @return Card Acceptor Name / Location
	 */
	public static String buildField43(){
		String de43 = String.format("%40s", dataElementService.getDataValue("DE43"));
		return de43;
	}
	/**
	 * Configurable Data Element
	 * @return Transaction Currency Code
	 */
	public static String buildField49(){
		return dataElementService.getDataValue("DE49"); 
	}
	/**
	 * Dynamic Data Element
	 * @return PIN Block
	 */
	public static String buildField52(){
		return "A1BCEF123456123A";
	}
	/**
	 * Configurable Data Element
	 * @return Additional Amount
	 */
	
	public static String buildField54(String de3, String de2, String amtType){
		String accountType = de3.substring(2, 3);
		String amountType = cardAccountService.getAmtType(de2);
		String currency=cardAccountService.getCurrency(de2);
		String flag=cardAccountService.getFlag(de2);
		String amount=cardAccountService.getBalance(de2);
		return accountType+amountType+currency+flag+amount;
	}
	
	public static String buildField90(String mti,String de11,String de7,String de32){
		String de33 = dataElementService.getDataValue("DE33");
		de32 = integerFormater(Integer.parseInt(de32),"00000000000");
		return mti+de11+de7+de32+de33;
	}
}
